﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
using Autodesk.Revit.DB.Electrical;
using Autodesk.Revit.DB.Mechanical;
using Autodesk.Revit.DB.Plumbing;
using Autodesk.Revit.UI.Selection;

namespace YArchitech.Revit.Electric.Common
{
	public class RevitFilter
	{
		public static FilteredElementCollector GetElementsOfType(Autodesk.Revit.DB.Document doc, Type type, BuiltInCategory bic)
		{
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc);
			filteredElementCollector.OfCategory(bic);
			filteredElementCollector.OfClass(type);
			return filteredElementCollector;
		}

		public static FilteredElementCollector GetElementsOfType(Autodesk.Revit.DB.Document doc, ElementId viewId, Type type, BuiltInCategory bic)
		{
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc, viewId);
			filteredElementCollector.OfCategory(bic);
			filteredElementCollector.OfClass(type);
			return filteredElementCollector;
		}

		public static FilteredElementCollector GetElementsOfType(Autodesk.Revit.DB.Document doc, Type type)
		{
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc);
			filteredElementCollector.OfClass(type);
			return filteredElementCollector;
		}

		public static FilteredElementCollector GetElementsOfType(Autodesk.Revit.DB.Document doc, ElementId viewId, Type type)
		{
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc, viewId);
			filteredElementCollector.OfClass(type);
			return filteredElementCollector;
		}

		public static FilteredElementCollector GetElementByCategory(Autodesk.Revit.DB.Document doc, BuiltInCategory builtInCategory)
		{
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc);
			filteredElementCollector.OfCategory(builtInCategory);
			return filteredElementCollector;
		}

		public static FilteredElementCollector GetElementByCategory(Autodesk.Revit.DB.Document doc, ElementId viewId, BuiltInCategory builtInCategory)
		{
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc, viewId);
			filteredElementCollector.OfCategory(builtInCategory);
			return filteredElementCollector;
		}

		public static IList<Element> GetProjectValidRooms(Autodesk.Revit.DB.Document doc)
		{
			return RevitFilter.GetElementByCategory(doc, BuiltInCategory.OST_Rooms).Where(delegate(Element r)
			{
				Room room = r as Room;
				return room.Location != null && room.GetBoundarySegments(new SpatialElementBoundaryOptions()).Count > 0;
			}).ToList<Element>();
		}

		public class SelectionRoomTagFilter : ISelectionFilter
		{
			public bool AllowElement(Element element)
			{
				return element is AnnotationSymbol && (element as AnnotationSymbol).Name == "房间照明标记";
			}

			public bool AllowReference(Reference refer, XYZ point)
			{
				return false;
			}
		}

		public class SocketFilter : ISelectionFilter
		{
			public SocketFilter(Autodesk.Revit.DB.Document m_doc)
			{
				this.doc = m_doc;
			}

			bool ISelectionFilter.AllowElement(Element elem)
			{
				return elem is FamilyInstance && elem.Category.Id.IntegerValue == -2001060 && (this.doc.GetElement(elem.GetTypeId()) as FamilySymbol).Family.get_Parameter(BuiltInParameter.FAMILY_CONTENT_PART_TYPE).AsInteger() == 0;
			}

			bool ISelectionFilter.AllowReference(Reference reference, XYZ position)
			{
				return false;
			}

			private Document doc;
		}

		public class PowerSwitchFilter : ISelectionFilter
		{
			public PowerSwitchFilter(Autodesk.Revit.DB.Document m_doc)
			{
				this.doc = m_doc;
			}

			bool ISelectionFilter.AllowElement(Element elem)
			{
				return elem is FamilyInstance && elem.Category.Id.IntegerValue == -2001060 && (this.doc.GetElement(elem.GetTypeId()) as FamilySymbol).Family.get_Parameter(BuiltInParameter.FAMILY_CONTENT_PART_TYPE).AsInteger() == 19;
			}

			bool ISelectionFilter.AllowReference(Reference reference, XYZ position)
			{
				return false;
			}

			private Document doc;
		}

		public class SelectionCableTrayFilter : ISelectionFilter
		{
			public bool AllowElement(Element element)
			{
				return element is CableTray;
			}

			public bool AllowReference(Reference refer, XYZ point)
			{
				return false;
			}
		}

		public class SelectionVerticalCableTrayFilter : ISelectionFilter
		{
			public bool AllowElement(Element element)
			{
				if (element is CableTray)
				{
					Line curve = (Line)((element as CableTray).Location as LocationCurve).Curve;
					XYZ xyz = (curve.GetEndPoint(1) - curve.GetEndPoint(0)).Normalize();
					if (xyz.IsAlmostEqualTo(XYZ.BasisZ) || xyz.IsAlmostEqualTo(-XYZ.BasisZ))
					{
						return true;
					}
				}
				return false;
			}

			public bool AllowReference(Reference refer, XYZ point)
			{
				return false;
			}
		}

		public class SelectionCableTrayConduitFilter : ISelectionFilter
		{
			public bool AllowElement(Element element)
			{
				return element is CableTrayConduitBase;
			}

			public bool AllowReference(Reference refer, XYZ point)
			{
				return false;
			}
		}

		public class OffsetDeviceFilter : ISelectionFilter
		{
			public bool AllowElement(Element element)
			{
				return element is CableTray || element is Duct || element is Pipe || element is Conduit;
			}

			public bool AllowReference(Reference refer, XYZ point)
			{
				return false;
			}
		}

		public class WireFilter : ISelectionFilter
		{
			public bool AllowElement(Element element)
			{
				return element is Wire;
			}

			public bool AllowReference(Reference refer, XYZ point)
			{
				return false;
			}
		}

		public class ConduitFilter : ISelectionFilter
		{
			public bool AllowElement(Element element)
			{
				return element is Conduit;
			}

			public bool AllowReference(Reference refer, XYZ point)
			{
				return false;
			}
		}

		public class PanelFilter : ISelectionFilter
		{
			public bool AllowElement(Element element)
			{
				string familyName = (element as FamilyInstance).Symbol.FamilyName;
				return element.Category.Id.IntegerValue == -2001040 && !familyName.Equals("局部等电位联结端子箱") && !familyName.Equals("总等电位联结端子箱");
			}

			public bool AllowReference(Reference refer, XYZ point)
			{
				return false;
			}
		}
	}
}
